package com.geek.factory.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.geek.factory.constant.SuccessConstant;
import com.geek.factory.entity.InventoryDistribution;
import com.geek.factory.entity.Product;
import com.geek.factory.entity.Material;
import com.geek.factory.entity.Warehouse;
import com.geek.factory.entity.Shelves;
import com.geek.factory.entity.WarehouseShelves;
import com.geek.factory.result.Result;
import com.geek.factory.service.IInventoryDistributionService;
import com.geek.factory.service.IProductService;
import com.geek.factory.service.IMaterialService;
import com.geek.factory.service.IWarehouseService;
import com.geek.factory.service.IShelvesService;
import com.geek.factory.service.IWarehouseShelvesService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 库存分布管理控制器
 * 注意：库存分布不应该直接编辑，应该通过出入库操作自动更新
 */
@RestController
@RequestMapping("/inventory")
@Api(tags = "后台系统的 - 库存分布模块")
@Slf4j
@CrossOrigin
public class InventoryDistributionController {

    @Autowired
    private IInventoryDistributionService inventoryDistributionService;

    @Autowired
    private IProductService productService;

    @Autowired
    private IMaterialService materialService;

    @Autowired
    private IWarehouseService warehouseService;

    @Autowired
    private IShelvesService shelvesService;
    
    @Autowired
    private IWarehouseShelvesService warehouseShelvesService;

    @ApiOperation("通过ID查询库存分布信息")
    @GetMapping("/{distributionId}")
    public Result findInventoryDistributionById(@ApiParam("库存分布ID") @PathVariable("distributionId") Integer distributionId) {
        InventoryDistribution inventoryDistribution = inventoryDistributionService.getById(distributionId);
        log.info("inventoryDistribution: {}", inventoryDistribution);
        if (inventoryDistribution != null) {
            // 添加关联信息
            Map<String, Object> result = enrichInventoryData(inventoryDistribution);
            return new Result(SuccessConstant.SUCCESS, "ok", result);
        }
        return new Result(SuccessConstant.FAIL, "库存分布记录不存在");
    }

    // 移除新增功能 - 库存分布应该通过出入库操作自动创建
    // @ApiOperation("新增库存分布")
    // @PostMapping
    // public Result addInventoryDistribution(@RequestBody InventoryDistribution inventoryDistribution) {
    //     // 移除新增功能
    //     return new Result(SuccessConstant.FAIL, "库存分布不能手动新增，请通过出入库操作管理");
    // }

    // 根据ID删除库存分布
    @ApiOperation("根据ID删除库存分布")
    @DeleteMapping("/{distributionId}")
    public Result deleteInventoryDistribution(@ApiParam("库存分布ID") @PathVariable("distributionId") Integer distributionId) {
        boolean isSuccess = inventoryDistributionService.removeById(distributionId);
        log.info("删除库存分布ID: {}, 结果: {}", distributionId, isSuccess);
        if (isSuccess) {
            return new Result(SuccessConstant.SUCCESS, "删除成功");
        }
        return new Result(SuccessConstant.FAIL, "删除失败");
    }

    // 批量删除库存分布
    @ApiOperation("批量删除库存分布")
    @DeleteMapping("/batch")
    public Result batchDeleteInventoryDistribution(@RequestBody Map<String, List<Integer>> request) {
        List<Integer> distributionIds = request.get("distributionIds");
        if (distributionIds == null || distributionIds.isEmpty()) {
            return new Result(SuccessConstant.FAIL, "请选择要删除的库存分布记录");
        }
        boolean isSuccess = inventoryDistributionService.removeByIds(distributionIds);
        log.info("批量删除库存分布IDs: {}, 结果: {}", distributionIds, isSuccess);
        if (isSuccess) {
            return new Result(SuccessConstant.SUCCESS, "批量删除成功");
        }
        return new Result(SuccessConstant.FAIL, "批量删除失败");
    }

    // 移除编辑功能 - 库存分布不应该直接编辑
    // @ApiOperation("修改库存分布信息")
    // @PutMapping("/{distributionId}")
    // public Result updateInventoryDistribution(@ApiParam("库存分布ID") @PathVariable("distributionId") Integer distributionId, @RequestBody InventoryDistribution inventoryDistribution) {
    //     return new Result(SuccessConstant.FAIL, "库存分布不能直接编辑，请通过出入库操作管理");
    // }

    // 调整库存数量 - 保留此功能用于特殊情况下的库存调整
    @ApiOperation("调整库存数量")
    @PutMapping("/{distributionId}/adjust")
    public Result adjustInventoryQuantity(
            @ApiParam("库存分布ID") @PathVariable("distributionId") Integer distributionId,
            @RequestBody Map<String, Object> request
    ) {
        Integer quantity = (Integer) request.get("quantity");
        String type = (String) request.get("type");
        Integer shelfId = (Integer) request.get("shelfId"); // 可以指定新的货柜ID进行库存转移

        if (quantity == null || type == null) {
            return new Result(SuccessConstant.FAIL, "参数错误");
        }

        InventoryDistribution inventoryDistribution = inventoryDistributionService.getById(distributionId);
        if (inventoryDistribution == null) {
            return new Result(SuccessConstant.FAIL, "库存分布记录不存在");
        }

        BigDecimal quantityBD = new BigDecimal(quantity);

        // 如果指定了新的货柜ID，则进行货柜间库存转移
        if (shelfId != null && !shelfId.equals(inventoryDistribution.getShelfId())) {
            // 检查目标货柜是否属于同一仓库
            LambdaQueryWrapper<WarehouseShelves> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(WarehouseShelves::getWarehouseId, inventoryDistribution.getWarehouseId());
            wrapper.eq(WarehouseShelves::getShelfId, shelfId);
            wrapper.eq(WarehouseShelves::getStatus, true);
            if (warehouseShelvesService.count(wrapper) == 0) {
                return new Result(SuccessConstant.FAIL, "目标货柜不属于同一仓库或未启用");
            }

            // 查找目标货柜的库存记录
            LambdaQueryWrapper<InventoryDistribution> targetWrapper = new LambdaQueryWrapper<>();
            targetWrapper.eq(InventoryDistribution::getWarehouseId, inventoryDistribution.getWarehouseId());
            targetWrapper.eq(InventoryDistribution::getShelfId, shelfId);
            if (inventoryDistribution.getProductId() != null) {
                targetWrapper.eq(InventoryDistribution::getProductId, inventoryDistribution.getProductId());
            } else if (inventoryDistribution.getMaterialId() != null) {
                targetWrapper.eq(InventoryDistribution::getMaterialId, inventoryDistribution.getMaterialId());
            }
            
            InventoryDistribution targetInventory = inventoryDistributionService.getOne(targetWrapper);
            
            // 如果目标货柜没有对应库存记录，创建一个新记录
            if (targetInventory == null) {
                targetInventory = new InventoryDistribution();
                targetInventory.setWarehouseId(inventoryDistribution.getWarehouseId());
                targetInventory.setShelfId(shelfId);
                targetInventory.setProductId(inventoryDistribution.getProductId());
                targetInventory.setMaterialId(inventoryDistribution.getMaterialId());
                targetInventory.setQuantity(BigDecimal.ZERO);
                targetInventory.setCreatedBy("admin");
                targetInventory.setCreatedTime(LocalDateTime.now());
            }
            
            // 执行转移
            if ("add".equals(type)) {
                if (inventoryDistribution.getQuantity().compareTo(quantityBD) < 0) {
                    return new Result(SuccessConstant.FAIL, "原货柜库存不足，无法转移");
                }
                inventoryDistribution.setQuantity(inventoryDistribution.getQuantity().subtract(quantityBD));
                targetInventory.setQuantity(targetInventory.getQuantity().add(quantityBD));
            } else if ("subtract".equals(type)) {
                if (targetInventory.getQuantity().compareTo(quantityBD) < 0) {
                    return new Result(SuccessConstant.FAIL, "目标货柜库存不足，无法转移");
                }
                targetInventory.setQuantity(targetInventory.getQuantity().subtract(quantityBD));
                inventoryDistribution.setQuantity(inventoryDistribution.getQuantity().add(quantityBD));
            } else {
                return new Result(SuccessConstant.FAIL, "操作类型错误");
            }
            
            targetInventory.setUpdatedBy("admin");
            targetInventory.setUpdatedTime(LocalDateTime.now());
            
            boolean targetSuccess = targetInventory.getDistributionId() == null ? 
                inventoryDistributionService.save(targetInventory) : 
                inventoryDistributionService.updateById(targetInventory);
                
            if (!targetSuccess) {
                return new Result(SuccessConstant.FAIL, "目标货柜库存更新失败");
            }
        } else {
            // 普通库存调整（不转移货柜）
            if ("add".equals(type)) {
                inventoryDistribution.setQuantity(inventoryDistribution.getQuantity().add(quantityBD));
            } else if ("subtract".equals(type)) {
                if (inventoryDistribution.getQuantity().compareTo(quantityBD) < 0) {
                    return new Result(SuccessConstant.FAIL, "库存不足");
                }
                inventoryDistribution.setQuantity(inventoryDistribution.getQuantity().subtract(quantityBD));
            } else {
                return new Result(SuccessConstant.FAIL, "操作类型错误");
            }
        }
        
        inventoryDistribution.setUpdatedBy("admin");
        inventoryDistribution.setUpdatedTime(LocalDateTime.now());
        boolean isSuccess = inventoryDistributionService.updateById(inventoryDistribution);
        log.info("调整库存数量: ID={}, 数量={}, 类型={}, 货柜转移={}, 结果={}", 
                distributionId, quantity, type, shelfId != null, isSuccess);
        
        if (isSuccess) {
            return new Result(SuccessConstant.SUCCESS, "调整成功", inventoryDistribution);
        }
        return new Result(SuccessConstant.FAIL, "调整失败");
    }

    @ApiOperation("分页查询库存分布列表")
    @GetMapping("/page")
    public Result getInventoryDistributionPage(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(required = false) Integer productId,
            @RequestParam(required = false) Integer materialId,
            @RequestParam(required = false) Integer warehouseId,
            @RequestParam(required = false) Integer shelfId,
            @RequestParam(required = false) String type,
            @RequestParam(required = false, defaultValue = "created_time") String orderBy,
            @RequestParam(required = false, defaultValue = "desc") String orderType
    ) {
        QueryWrapper<InventoryDistribution> wrapper = new QueryWrapper<>();
        if (productId != null) {
            wrapper.eq("product_id", productId);
        }
        if (materialId != null) {
            wrapper.eq("material_id", materialId);
        }
        if (warehouseId != null) {
            wrapper.eq("warehouse_id", warehouseId);
        }
        if (shelfId != null) {
            wrapper.eq("shelf_id", shelfId);
        }
        if (StringUtils.isNotBlank(type)) {
            if ("product".equals(type)) {
                wrapper.isNotNull("product_id");
            } else if ("material".equals(type)) {
                wrapper.isNotNull("material_id");
            }
        }
        
        // 添加排序，处理字段名映射
        if (StringUtils.isNotBlank(orderBy)) {
            // 处理字段名映射
            String dbFieldName = orderBy;
            if ("createdTime".equals(orderBy)) {
                dbFieldName = "created_time";
            } else if ("updatedTime".equals(orderBy)) {
                dbFieldName = "updated_time";
            }
            
            if ("desc".equalsIgnoreCase(orderType)) {
                wrapper.orderByDesc(dbFieldName);
            } else {
                wrapper.orderByAsc(dbFieldName);
            }
        }

        Page<InventoryDistribution> page = inventoryDistributionService.page(new Page<>(pageNum, pageSize), wrapper);

        // 为每条记录添加关联信息
        List<Map<String, Object>> enrichedRecords = page.getRecords().stream()
                .map(this::enrichInventoryData)
                .collect(Collectors.toList());

        Map<String, Object> data = new HashMap<>();
        data.put("records", enrichedRecords);
        data.put("total", page.getTotal());
        data.put("current", page.getCurrent());
        data.put("size", page.getSize());
        data.put("pages", page.getPages());

        return new Result(SuccessConstant.SUCCESS, "查询成功", data);
    }

    @ApiOperation("获取库存统计信息")
    @GetMapping("/stats")
    public Result getInventoryStats(@RequestParam(required = false) Integer warehouseId) {
        // 这里需要根据实际业务逻辑实现统计功能
        // 可以调用Service层的方法来获取统计数据
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalProducts", 0);
        stats.put("totalMaterials", 0);
        stats.put("totalWarehouses", 0);
        stats.put("totalQuantity", 0);

        return new Result(SuccessConstant.SUCCESS, "查询成功", stats);
    }

    @ApiOperation("获取所有库存分布列表")
    @GetMapping("/list")
    public Result getAllInventoryDistributions(
            @RequestParam(required = false, defaultValue = "created_time") String orderBy,
            @RequestParam(required = false, defaultValue = "desc") String orderType
    ) {
        QueryWrapper<InventoryDistribution> wrapper = new QueryWrapper<>();
        
        // 添加排序，处理字段名映射
        if (StringUtils.isNotBlank(orderBy)) {
            // 处理字段名映射
            String dbFieldName = orderBy;
            if ("createdTime".equals(orderBy)) {
                dbFieldName = "created_time";
            } else if ("updatedTime".equals(orderBy)) {
                dbFieldName = "updated_time";
            }
            
            if ("desc".equalsIgnoreCase(orderType)) {
                wrapper.orderByDesc(dbFieldName);
            } else {
                wrapper.orderByAsc(dbFieldName);
            }
        }
        
        List<InventoryDistribution> inventoryDistributions = inventoryDistributionService.list(wrapper);

        // 为每条记录添加关联信息
        List<Map<String, Object>> enrichedRecords = inventoryDistributions.stream()
                .map(this::enrichInventoryData)
                .collect(Collectors.toList());

        return new Result(SuccessConstant.SUCCESS, "查询成功", enrichedRecords);
    }

    /**
     * 为库存分布数据添加关联信息（产品名称、原料名称、仓库名称等）
     */
    private Map<String, Object> enrichInventoryData(InventoryDistribution inventory) {
        Map<String, Object> result = new HashMap<>();

        // 复制原始数据
        result.put("distributionId", inventory.getDistributionId());
        result.put("productId", inventory.getProductId());
        result.put("materialId", inventory.getMaterialId());
        result.put("warehouseId", inventory.getWarehouseId());
        result.put("shelfId", inventory.getShelfId());
        result.put("quantity", inventory.getQuantity());
        result.put("createdBy", inventory.getCreatedBy());
        result.put("createdTime", inventory.getCreatedTime());
        result.put("updatedBy", inventory.getUpdatedBy());
        result.put("updatedTime", inventory.getUpdatedTime());

        // 添加产品信息
        if (inventory.getProductId() != null) {
            Product product = productService.getById(inventory.getProductId());
            if (product != null) {
                result.put("productName", product.getName());
                result.put("productCode", product.getModel()); // 使用model字段作为产品编码
                result.put("itemType", "product");
            }
        }

        // 添加原料信息
        if (inventory.getMaterialId() != null) {
            Material material = materialService.getById(inventory.getMaterialId());
            if (material != null) {
                result.put("materialName", material.getMaterialName());
                result.put("materialCode", material.getMaterialCode());
                result.put("itemType", "material");
            }
        }

        // 添加仓库信息
        if (inventory.getWarehouseId() != null) {
            Warehouse warehouse = warehouseService.getById(inventory.getWarehouseId());
            if (warehouse != null) {
                result.put("warehouseName", warehouse.getWarehouseName());
                result.put("warehouseCode", warehouse.getWarehouseCode());
            }
        }
        
        // 添加货柜信息
        if (inventory.getShelfId() != null) {
            Shelves shelves = shelvesService.getById(inventory.getShelfId());
            if (shelves != null) {
                result.put("shelfName", shelves.getShelfName());
                result.put("shelfCode", shelves.getShelfCode());
                result.put("locationCode", shelves.getLocationCode());
            }
        }

        return result;
    }
    @ApiOperation("货柜间库存转移")
    @PostMapping("/transfer")
    public Result transferInventory(@RequestBody Map<String, Object> request) {
        Integer distributionId = (Integer) request.get("distributionId");
        Integer sourceShelfId = (Integer) request.get("sourceShelfId");
        Integer targetShelfId = (Integer) request.get("targetShelfId");
        Integer warehouseId = (Integer) request.get("warehouseId");
        Integer productId = (Integer) request.get("productId");
        Integer materialId = (Integer) request.get("materialId");
        Integer quantity = (Integer) request.get("quantity");

        if (distributionId == null || sourceShelfId == null || targetShelfId == null || warehouseId == null || quantity == null) {
            return new Result(SuccessConstant.FAIL, "参数不完整");
        }
        if (sourceShelfId.equals(targetShelfId)) {
            return new Result(SuccessConstant.FAIL, "目标货柜不能与当前货柜相同");
        }

        // 查找源库存
        LambdaQueryWrapper<InventoryDistribution> sourceWrapper = new LambdaQueryWrapper<>();
        sourceWrapper.eq(InventoryDistribution::getWarehouseId, warehouseId);
        sourceWrapper.eq(InventoryDistribution::getShelfId, sourceShelfId);
        if (productId != null) {
            sourceWrapper.eq(InventoryDistribution::getProductId, productId);
        } else if (materialId != null) {
            sourceWrapper.eq(InventoryDistribution::getMaterialId, materialId);
        }
        InventoryDistribution sourceInventory = inventoryDistributionService.getOne(sourceWrapper);
        if (sourceInventory == null) {
            return new Result(SuccessConstant.FAIL, "源货柜库存不存在");
        }
        if (sourceInventory.getQuantity().compareTo(new java.math.BigDecimal(quantity)) < 0) {
            return new Result(SuccessConstant.FAIL, "源货柜库存不足");
        }

        // 查找目标库存
        LambdaQueryWrapper<InventoryDistribution> targetWrapper = new LambdaQueryWrapper<>();
        targetWrapper.eq(InventoryDistribution::getWarehouseId, warehouseId);
        targetWrapper.eq(InventoryDistribution::getShelfId, targetShelfId);
        if (productId != null) {
            targetWrapper.eq(InventoryDistribution::getProductId, productId);
        } else if (materialId != null) {
            targetWrapper.eq(InventoryDistribution::getMaterialId, materialId);
        }
        InventoryDistribution targetInventory = inventoryDistributionService.getOne(targetWrapper);

        // 如果目标没有库存记录，创建
        if (targetInventory == null) {
            targetInventory = new InventoryDistribution();
            targetInventory.setWarehouseId(warehouseId);
            targetInventory.setShelfId(targetShelfId);
            targetInventory.setProductId(productId);
            targetInventory.setMaterialId(materialId);
            targetInventory.setQuantity(java.math.BigDecimal.ZERO);
            targetInventory.setCreatedBy("admin");
            targetInventory.setCreatedTime(LocalDateTime.now());
        }

        // 执行转移
        sourceInventory.setQuantity(sourceInventory.getQuantity().subtract(new java.math.BigDecimal(quantity)));
        targetInventory.setQuantity(targetInventory.getQuantity().add(new java.math.BigDecimal(quantity)));
        targetInventory.setUpdatedBy("admin");
        targetInventory.setUpdatedTime(LocalDateTime.now());

        boolean sourceSuccess = inventoryDistributionService.updateById(sourceInventory);
        boolean targetSuccess = (targetInventory.getDistributionId() == null)
                ? inventoryDistributionService.save(targetInventory)
                : inventoryDistributionService.updateById(targetInventory);

        if (sourceSuccess && targetSuccess) {
            return new Result(SuccessConstant.SUCCESS, "转移成功");
        } else {
            return new Result(SuccessConstant.FAIL, "转移失败");
        }
    }
    @ApiOperation("根据货柜ID查询该货柜实际存放的物品和数量")
    @GetMapping("/by-shelf")
    public Result getItemsByShelf(@RequestParam Integer shelfId) {
        // 查该货柜下所有有库存的分布
        List<InventoryDistribution> list = inventoryDistributionService.list(
                new LambdaQueryWrapper<InventoryDistribution>()
                        .eq(InventoryDistribution::getShelfId, shelfId)
                        .gt(InventoryDistribution::getQuantity, 0)
        );

        // 组装前端需要的格式
        List<Map<String, Object>> result = list.stream().map(inv -> {
            Map<String, Object> map = new HashMap<>();
            map.put("distributionId", inv.getDistributionId());
            map.put("productId", inv.getProductId());
            map.put("materialId", inv.getMaterialId());
            map.put("quantity", inv.getQuantity());
            map.put("unit", ""); // 默认空，后面查
            map.put("itemType", inv.getProductId() != null ? "product" : "material");
            if (inv.getProductId() != null) {
                Product product = productService.getById(inv.getProductId());
                if (product != null) {
                    map.put("itemName", product.getName());
                    map.put("itemCode", product.getModel()); // 使用model字段作为产品编码
                    map.put("unit", ""); // Product不再有unit字段，设为空字符串
                }
            }
            if (inv.getMaterialId() != null) {
                Material material = materialService.getById(inv.getMaterialId());
                if (material != null) {
                    map.put("itemName", material.getMaterialName());
                    map.put("itemCode", material.getMaterialCode());
                    map.put("unit", material.getUnit());
                }
            }
            return map;
        }).collect(Collectors.toList());

        return new Result(SuccessConstant.SUCCESS, "查询成功", result);
    }
}